#pragma once

#include <iostream>
#include <thread>
#include <string>
#include <unistd.h>
#include <queue>

const int default_cap = 5; // 默认容量5

// 阻塞队列类
template <typename T>
class BlockQueue
{
private:
    // 判断队列是否为满
    bool _is_full() const { return _queue.size() == _cap; }

    // 判断队列是否为空
    bool _is_empty() const { return _queue.empty(); }

public:
    // 构造函数
    BlockQueue(int cap = default_cap) : _cap(cap)
    {
        // 初始化互斥锁
        pthread_mutex_init(&_mutex, NULL);
        // 初始化非空条件变量
        pthread_cond_init(&_not_empty, NULL);
        // 初始化非满条件变量
        pthread_cond_init(&_not_full, NULL);
    }

    // 入队函数，生产者调用
    void enqueue(const T &item)
    {
        pthread_mutex_lock(&_mutex); // 加互斥锁
        while (_is_full())
        {
            // 队列已满，等待
            _psleep++; // 生产者休眠数量加1

            pthread_cond_wait(&_not_full, &_mutex);
            _psleep--; // 生产者休眠数量减1
        }

        // 队列未满，入队
        _queue.push(item);

        // 解锁
        if (_csleep > 0)
        {
            pthread_cond_signal(&_not_empty); // 通知非空条件变量
            std::cout << "正在唤醒消费者..." << std::endl;
        }
        pthread_mutex_unlock(&_mutex);
    }

    // 出队函数，消费者调用
    T dequeue()
    {
        pthread_mutex_lock(&_mutex); // 加互斥锁

        while (_is_empty())
        {
            // 队列为空，等待
            _csleep++; // 消费者休眠数量加1

            pthread_cond_wait(&_not_empty, &_mutex);
            _psleep--; // 生产者休眠数量减1
        }

        // 队列非空，出队
        T item = _queue.front();
        _queue.pop();

        // 解锁
        if (_psleep > 0)
        {
            pthread_cond_signal(&_not_full); // 通知非满条件变量
            std::cout << "正在唤醒生产者..." << std::endl;
        }
        pthread_mutex_unlock(&_mutex);

        return item;
    }

    // 析构函数
    ~BlockQueue()
    {
        // 销毁互斥锁
        pthread_mutex_destroy(&_mutex);
        // 销毁非空条件变量
        pthread_cond_destroy(&_not_empty);
        // 销毁非满条件变量
        pthread_cond_destroy(&_not_full);
    }

private:
    std::queue<T> _queue; // 队列
    int _cap;             // 容量

    pthread_mutex_t _mutex;    // 互斥锁
    pthread_cond_t _not_empty; // 非空条件变量
    pthread_cond_t _not_full;  // 非满条件变量

    int _psleep; // 生产者休眠数量
    int _csleep; // 消费者休眠数量
};